home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Oh!X 2001 Spring
/
Oh!X 2001 Spring Special CD-ROM (Japan).7z
/
Oh!X 2001 Spring Special CD-ROM (Japan) (Track 1).bin
/
TCLTK
/
SEVEN
/
seven.tcl
next >
Wrap
Text File
|
2000-05-07
|
12KB
|
509 lines
#
# seven.tcl : 同じ高さにある足して7になるカードを取り除く
#
# Copyright (C) 1999 by Makoto Hiroi
#
# 外部変数
# board() : 盤面(データを格納)
# 上位 4 ビットで色、下位 4 ビットで数字を表す
# number() : テキスト ID を格納
# numstr() : 表示する文字列
# color() : 表示する色
# piece() : 図形 ID を格納
# px,py : 選択した数字の座標( -1 は未選択 )
# rest : 残りの枚数
# play_flag : ゲームの状態
# 0 : not play
# 1 : play
# 2 : use search
# 4 : 検索中
# buff1 : メッセージ表示用バッファ
# buff2 : 名前入力用バッファ
# id : after コマンドが返す固有番号
# name() : トップテン(1 - 10, 0 is dummy)
# date()
# score()
#
# 色
set color(0) red
set color(1) blue
set color(2) green
set color(3) gold
# ワイルドカード用
set color(4) black
# 数字
set numstr(0) ""
set numstr(1) "1"
set numstr(2) "2"
set numstr(3) "3"
set numstr(4) "4"
set numstr(5) "5"
set numstr(6) "6"
# ワイルドカード(どの場所の数字も入れ替えることができる)
set numstr(7) "?"
# 初期化
set play_flag 0
# ヘルプファイルの表示
proc help {} {
global path_name
if {![winfo exist .t0]} {
toplevel .t0
wm title .t0 "Seven Help"
text .t0.text -yscrollcommand ".t0.scroll set"
scrollbar .t0.scroll -command ".t0.text yview"
pack .t0.scroll -side right -fill y
pack .t0.text -side left
# ファイルの読み込み
set f [open "$path_name/sevenhelp.txt" r]
while {![eof $f]} {
.t0.text insert end [read $f 1000]
}
close $f
}
}
# スコアファイルリード
proc read_score_file {} {
global score_file name date score
set i 1
if [file exists $score_file] {
# ファイルの読み込み
set f [open $score_file r]
while {[gets $f line] >= 0} {
set l [split $line "\t"]
set name($i) [lindex $l 0]
set date($i) [lindex $l 1]
set score($i) [lindex $l 2]
incr i
}
close $f
}
set now_date [clock seconds]
while {$i <= 10} {
set name($i) ""
set date($i) $now_date
# 5999 は 99:59 です
set score($i) 5999
incr i
}
}
# スコアファイルライト
proc write_score_file {} {
global score_file name date score
set f [open $score_file w]
for {set i 1} {$i <= 10} {incr i} {
puts $f [format "%s\t%d\t%d" $name($i) $date($i) $score($i)]
}
close $f
}
# ********** スコア表示 ********
# 秒数をスコアに変換
proc change_seconds {s} {
return [format "%02d:%02d" [expr $s / 60] [expr $s % 60]]
}
#
# トップテンウィンドウを開く
#
proc open_score_window {ranking} {
global name date score
if [winfo exists .t1] {
destroy .t1
}
toplevel .t1
wm title .t1 "Top 10"
frame .t1.f0
frame .t1.f1
label .t1.f0.l0 -text "順位 名前" -anchor w
label .t1.f1.l0 -text "記録 日付 " -anchor w
pack .t1.f0.l0 -fill x
pack .t1.f1.l0 -fill x
for {set i 1} {$i <= 10} {incr i} {
label .t1.f0.l$i -text [format "%4d %-20s" $i $name($i)] -anchor w
label .t1.f1.l$i -text [format "%5s %8s" \
[change_seconds $score($i)] \
[clock format $date($i) -format "%y/%m/%d"]]
pack .t1.f0.l$i -fill x
pack .t1.f1.l$i -fill x
}
if {$ranking > 0} {
.t1.f0.l$ranking configure -fg red
.t1.f1.l$ranking configure -fg red
}
pack .t1.f0 .t1.f1 -side left
}
# ベストテンに入るか
proc check_hi_score {now_score} {
global score
for {set i 1} {$i <= 10} {incr i} {
if {$score($i) > $now_score} {
# ベストテンに入ったよ
return $i
}
}
return 0
}
# スコアの更新
proc update_score {n d s o} {
global name date score
for {set i 9} {$i >= $o} {incr i -1} {
set j [expr $i + 1]
set name($j) $name($i)
set date($j) $date($i)
set score($j) $score($i)
}
set name($o) $n
set date($o) $d
set score($o) $s
}
# トップテンの名前入力
proc input_hi_score_name {ranking} {
global buff2
set buff2 ""
toplevel .t2
wm title .t2 "Input Your Name"
wm geometry .t2 "+[expr [winfo x .] + 120]+[expr [winfo y .] + 180]"
label .t2.l0 -text [format "おめでとう! %d 位です" $ranking]
label .t2.l1 -text "名前を入力してね"
entry .t2.e0 -textvariable buff2
focus -force .t2.e0
grab set -global .t2
bind .t2.e0 <Return> {
# 入力チェックが必要か
if {$buff2 != ""} {
destroy .t2
}
}
pack .t2.l0 .t2.l1 .t2.e0
}
# 盤面から色を求める
proc get_color {x y} {
global board
return [expr $board($x,$y) / 16]
}
# 盤面から数字を求める
proc get_number {x y} {
global board
return [expr $board($x,$y) % 16]
}
# 終了チェック
proc check_finish {} {
global board rest buff2 play_flag id time
if {$rest(normal) == 0} {
# 終了
set t [clock seconds]
set s [expr [clock seconds] - $time]
after cancel $id
set ranking [check_hi_score $s]
if {$ranking > 0 && $play_flag == 1} {
input_hi_score_name $ranking
tkwait window .t2
update_score $buff2 $t $s $ranking
write_score_file
open_score_window $ranking
} else {
tk_messageBox -type ok \
-message [format "おめでとう %s です" [change_seconds $s]]
}
return 1
} elseif {[search_piece] == "" && $rest(wild) == 0} {
after cancel $id
tk_messageBox -type ok -message "手詰まりです"
return 1
}
return 0
}
# 牌を取り除く
proc remove_piece {x y} {
global board piece rest
# 色を元に戻す
.c0 itemconfigure $piece($x,$y) -fill white
# 下に落とすだけ
while {$y > 0} {
set y1 [expr $y - 1]
set board($x,$y) $board($x,$y1)
incr y -1
}
set board($x,0) 0
draw_board_line $x
}
# 取れる牌を探す
proc search_piece {} {
global board piece
set result ""
for {set y 0} {$y < 10} {incr y} {
for {set x 0} {$x < 8} {incr x} {
if {$board($x,$y) != 0} {
set i [expr $x + 1]
while {$i < 8} {
if {$board($i,$y) != 0} {
if {[get_color $x $y] == [get_color $i $y] && \
[expr [get_number $x $y] + [get_number $i $y]] == 7} {
set result [concat $result $piece($x,$y) $piece($i,$y)]
}
}
incr i
}
}
}
}
return $result
}
# 検索
proc search {} {
global play_flag px py
if {!($play_flag & 0x03)} return
if {$px != -1} {
# 選択していたらキャンセルして表示する
push_piece $px $py
}
set play_flag 4
set pieces [search_piece]
set len [llength $pieces]
set i 0
while {$i < $len} {
set p1 [lindex $pieces $i]
incr i
set p2 [lindex $pieces $i]
incr i
.c0 itemconfigur $p1 -fill darkgray
.c0 itemconfigur $p2 -fill darkgray
update
after 500
.c0 itemconfigur $p1 -fill white
.c0 itemconfigur $p2 -fill white
}
set play_flag 2
}
# カードの交換
proc change_card {x y} {
global px py piece board rest time
if {[get_number $x $y] != 7} {
.c0 itemconfigure $piece($x,$y) -fill darkgray
update
after 250
# ワイルドカードに挿入
set board($px,$py) $board($x,$y)
.c0 itemconfigure $piece($px,$py) -fill white
draw_board_line $px
# 移動したカードを消去
remove_piece $x $y
incr rest(wild) -1
# 10 秒加算する
incr time -10
set px -1
set py -1
}
}
# 数字を押したよ
proc push_piece {x y} {
global play_flag px py piece id rest
if {!($play_flag & 0x03)} return
if {$px == $x && $py == $y} {
# 同じ数字を押したらキャンセル
set px -1
set py -1
.c0 itemconfigure $piece($x,$y) -fill white
} elseif {$px == -1} {
# 最初の選択
set px $x
set py $y
.c0 itemconfigure $piece($x,$y) -fill darkgray
} else {
# 2回目
if {$py == $y && [get_color $px $py] == [get_color $x $y] && \
[expr [get_number $px $py] + [get_number $x $y]] == 7} {
# 消せるよ
.c0 itemconfigure $piece($x,$y) -fill darkgray
update
after 250
# 上にある牌から消去する
if {$py > $y} {
remove_piece $x $y
remove_piece $px $py
} else {
remove_piece $px $py
remove_piece $x $y
}
incr rest(normal) -2
set px -1
set py -1
} elseif {[get_number $px $py] == 7} {
# カードの交換
change_card $x $y
}
# 手詰まりチェック
if [check_finish] {
set play_flag 0
}
}
}
# ********** 初期化ルーチン **********
# 盤面の初期化
proc make_board {} {
global board
# piece_table は局所変数
for {set i 0; set c 0} {$c < 4} {incr c} {
for {set n 1} {$n <= 6} {incr n} {
# piece_tabale の初期化
for {set j 0} {$j < 3} {incr j} {
set piece_table($i) [expr $c * 16 + $n]
incr i
}
}
}
# ワイルドカードのセット
for {set c 0} {$c < 8} {incr c} {
# 4 * 16 + 7 = 71
set piece_table($i) 71
incr i
}
# 乱数でかき回す
for {set j 0} {$j < $i} {incr j} {
set n [expr int( rand() * $i )]
set temp $piece_table($n)
set piece_table($n) $piece_table($j)
set piece_table($j) $temp
}
# board にセット
set i 0
for {set y 0} {$y < 10} {incr y} {
for {set x 0} {$x < 8} {incr x} {
set board($x,$y) $piece_table($i)
incr i
}
}
}
# 縦の1列を描く
proc draw_board_line {x} {
global piece number numstr color
for {set y 0} {$y < 10} {incr y} {
set c [get_color $x $y]
set n [get_number $x $y]
if {$n != 0} {
.c0 itemconfigure $number($x,$y) -text $numstr($n) -fill $color($c)
.c0 raise $piece($x,$y)
.c0 raise $number($x,$y)
} else {
.c0 lower $piece($x,$y)
.c0 lower $number($x,$y)
}
}
}
# 全体を表示する
proc draw_board {} {
for {set x 0} {$x < 8} {incr x} {
draw_board_line $x
}
}
# メッセージの表示
proc display_message {} {
global time buff1
set t [expr [clock seconds] - $time]
set buff1 [format "時間 %5s" [change_seconds $t]]
}
# 時間の表示
proc display_time {} {
global id
display_message
set id [after 1000 display_time]
}
# ゲームの開始
proc start_game {} {
global play_flag rest px py id time
if {$play_flag > 0} {
after cancel $id
}
make_board
draw_board
set rest(normal) 72
set rest(wild) 8
set play_flag 1
set px -1
set py -1
set time [clock seconds]
display_time
}
# ********** メニューの設定 **********
menu .m -type menubar
. configure -menu .m
.m add cascade -label "Games" -under 0 -menu .m.m1
.m add command -label "Search" -under 0 -command "search"
.m add command -label "Help" -under 0 -command "help"
menu .m.m1 -tearoff no
.m.m1 add command -label "Start" -under 0 -command "start_game"
.m.m1 add command -label "HiScore" -under 0 -command "open_score_window 0"
.m.m1 add separator
.m.m1 add command -label "Exit" -under 0 -command "exit"
# オプションの設定
option add *font "{MS ゴシック} 12"
# **********画面の生成 **********
canvas .c0 -width 272 -height 340
# 背景
.c0 create rectangle 0 0 271 339 -fill darkgreen
for {set y 0} {$y < 10} {incr y} {
for {set x 0} {$x < 8} {incr x} {
set x1 [expr $x * 34]
set x2 [expr $x1 + 33]
set y1 [expr $y * 34]
set y2 [expr $y1 + 33]
set piece($x,$y) [.c0 create rectangle $x1 $y1 $x2 $y2 -fill white]
set number($x,$y) [.c0 create text [expr $x1 + 17] [expr $y1 + 17] \
-text " " \
-font "{MS ゴシック} 24"]
.c0 bind $piece($x,$y) <Button-1> "push_piece $x $y"
.c0 bind $number($x,$y) <Button-1> "push_piece $x $y"
}
}
# 表示用ラベル
label .l1 -textvariable buff1 -bg darkgreen -fg white -anchor e
pack .l1 .c0 -fill x
# 窓の題名
wm title . "Seven"
wm resizable . 0 0
# 初期化
set path_name [file dirname $argv0]
set score_file "$path_name/SEVEN.SCO"
expr srand( [clock seconds] )
# スコアファイルのリード
read_score_file
focus -force .
# end of file